home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1990 Free Software Foundation, Inc.
-
- This file is part of Oleo, the GNU Spreadsheet.
-
- Oleo is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- Oleo is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Oleo; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #define obstack_chunk_alloc ck_malloc
- #define obstack_chunk_free free
- #include "obstack.h"
- #include "funcdef.h"
- #include "sysdef.h"
-
- #include "global.h"
- #include "cell.h"
- #include "eval.h"
- #include "errors.h"
-
- struct value {
- int type;
- union vals x;
- };
-
- #define Float x.c_d
- #define String x.c_s
- #define Int x.c_l
- #define Value x.c_i
- #define Rng x.c_r
-
- #define ERROR(x) \
- { \
- p->Value=x; \
- p->type=TYP_ERR;\
- return; \
- }
-
-
- static int
- cell FUN4(long,row, long,col, char *,dowhat, struct value *,p)
- {
- struct func {
- char *name;
- int typ;
- };
-
- static struct func cell_funs[] = {
- { "row", TYP_INT },
- { "column", TYP_INT },
- { "width", TYP_INT },
- { "lock", TYP_STR },
- { "protection", TYP_STR },
- { "justify", TYP_STR },
- { "alignment", TYP_STR },
- { "fmt", TYP_STR },
- { "format", TYP_STR },
- { "type", TYP_STR },
- { "formula", TYP_STR },
- { "value", 0 },
- {0, 0 }
- };
-
- CELL *cell_ptr;
- char *strptr;
- struct func *func;
- struct func *f1;
- int n;
- extern default_lock;
-
- n=strlen(dowhat)-1;
- f1=0;
- for(func=cell_funs;func->name;func++)
- if( func->name[0]==dowhat[0]
- && (n==0 || !strincmp(&(func->name[1]),&dowhat[1],n))) {
- if(f1)
- return BAD_INPUT;
- f1=func;
- }
- if(!f1)
- return BAD_INPUT;
- p->type=f1->typ;
- switch(f1-cell_funs) {
- case 0:
- p->Int=row;
- break;
- case 1:
- p->Int=col;
- break;
- case 2:
- p->Int=get_width(col);
- break;
- case 3:
- case 4:
- p->String=((cell_ptr=find_cell(row,col)) ? GET_LCK(cell_ptr) : default_lock) ? "locked" : "unlocked";
- break;
- case 5:
- case 6:
- p->String=jst_to_str((cell_ptr=find_cell(row,col)) ? GET_JST(cell_ptr) : 0);
- break;
- case 7:
- case 8:
- p->String=fmt_to_str((cell_ptr=find_cell(row,col)) ? GET_FMT(cell_ptr) : 0);
- break;
- case 9:
- cell_ptr=find_cell(row,col);
- if(cell_ptr)
- switch(GET_TYP(cell_ptr)) {
- case TYP_FLT:
- p->String="float";
- break;
- case TYP_INT:
- p->String="integer";
- break;
- case TYP_STR:
- p->String="string";
- break;
- case TYP_BOL:
- p->String="boolean";
- break;
- case TYP_ERR:
- p->String="error";
- break;
- default:
- p->String="Unknown";
- }
- else
- p->String="null";
- break;
- case 10:
- cell_ptr=find_cell(row,col);
- if(cell_ptr && (GET_TYP(cell_ptr) || cell_ptr->cell_formula)) {
- strptr=decomp(row,col,cell_ptr);
- p->String=obstack_alloc(&tmp_mem,strlen(strptr)+1);
- strcpy(p->String,strptr);
- decomp_free();
- } else
- p->String="";
- break;
- case 11:
- cell_ptr=find_cell(row,col);
- if(cell_ptr) {
- p->type=GET_TYP(cell_ptr);
- p->x=cell_ptr->c_z;
- } else
- p->type=0;
- break;
- default:
- return BAD_INPUT;
- }
- return 0;
- }
-
-
- static void
- do_curcell FUN1(struct value *,p)
- {
- extern CELLREF curow,cucol;
- int tmp;
-
- tmp=cell(curow,cucol,p->String,p);
- if(tmp)
- ERROR(tmp);
- }
-
- static void
- do_my FUN1(struct value *,p)
- {
- int tmp;
-
- tmp=cell(cur_row,cur_col,p->String,p);
- if(tmp)
- ERROR(tmp);
- }
-
- /* Note that the second argument may be *anything* including ERROR. If it is
- error, we find the first occurence of that ERROR in the range */
-
- static void
- do_member FUN1(struct value *,p)
- {
- CELLREF crow;
- CELLREF ccol;
- int foundit;
- CELL *cell_ptr;
- struct rng *rptr;
-
- rptr= &(p->Rng);
- find_cells_in_range(&(p->Rng));
- while(cell_ptr=next_row_col_in_range(&crow,&ccol)) {
- if(GET_TYP(cell_ptr)!=(p+1)->type)
- continue;
- switch((p+1)->type) {
- case 0:
- foundit=1;
- break;
- case TYP_FLT:
- foundit=cell_ptr->cell_flt==(p+1)->Float;
- break;
- case TYP_INT:
- foundit=cell_ptr->cell_int==(p+1)->Int;
- break;
- case TYP_STR:
- foundit= !strcmp(cell_ptr->cell_str,(p+1)->String);
- break;
- case TYP_BOL:
- foundit=cell_ptr->cell_bol==(p+1)->Value;
- break;
- case TYP_ERR:
- foundit=cell_ptr->cell_err==(p+1)->Value;
- break;
- #ifdef TEST
- default:
- panic("Unknown type (%d) in member",(p+1)->type);
- foundit=0;
- #endif
- }
- if(foundit) {
- no_more_cells();
- p->Int = 1 + crow-p->Rng.lr + (ccol-p->Rng.lc)*(1+p->Rng.hr-p->Rng.lr);
- p->type=TYP_INT;
- return;
- }
- }
- p->Int=0L;
- p->type=TYP_INT;
- }
-
- static void
- do_smember FUN1(struct value *,p)
- {
- CELLREF crow;
- CELLREF ccol;
- CELL *cell_ptr;
- char *string;
-
- string=(p+1)->String;
- find_cells_in_range(&(p->Rng));
- while(cell_ptr=next_row_col_in_range(&crow,&ccol)) {
- if( (GET_TYP(cell_ptr)==0 && string[0]=='\0')
- || (cell_ptr && GET_TYP(cell_ptr)==TYP_STR && strstr(string,cell_ptr->cell_str))) {
- no_more_cells();
- p->Int = 1 + (crow-p->Rng.lr)
- + (ccol-p->Rng.lc)*(1+(p->Rng.hr-p->Rng.lr));
- p->type=TYP_INT;
- return;
- }
- }
- p->Int = 0L;
- p->type=TYP_INT;
- }
-
- static void
- do_members FUN1(struct value *,p)
- {
- CELLREF crow;
- CELLREF ccol;
- CELL *cell_ptr;
- char *string;
-
- string=(p+1)->String;
- find_cells_in_range(&(p->Rng));
- while(cell_ptr=next_row_col_in_range(&crow,&ccol)) {
- if(GET_TYP(cell_ptr)!=TYP_STR)
- continue;
- if(strstr(cell_ptr->cell_str,string)) {
- no_more_cells();
- p->Int = 1 + (crow-p->Rng.lr)
- + (ccol-p->Rng.lc)*(1+(p->Rng.hr-p->Rng.lr));
- p->type=TYP_INT;
- return;
- }
- }
- p->Int = 0L;
- p->type=TYP_INT;
- }
-
- static void
- do_pmember FUN1(struct value *,p)
- {
- CELLREF crow;
- CELLREF ccol;
- CELL *cell_ptr;
- char *string;
-
- string=(p+1)->String;
- find_cells_in_range(&(p->Rng));
- while(cell_ptr=next_row_col_in_range(&crow,&ccol)) {
- if( (GET_TYP(cell_ptr)==0 && string[0]=='\0')
- || (cell_ptr && GET_TYP(cell_ptr)==TYP_STR && !strncmp(string,cell_ptr->cell_str,strlen(cell_ptr->cell_str)))) {
- no_more_cells();
- p->Int = 1 + (crow-p->Rng.lr)
- + (ccol-p->Rng.lc)*(1+(p->Rng.hr-p->Rng.lr));
- p->type=TYP_INT;
- return;
- }
- }
- p->Int = 0L;
- p->type=TYP_INT;
- }
-
- static void
- do_memberp FUN1(struct value *,p)
- {
- CELLREF crow;
- CELLREF ccol;
- CELL *cell_ptr;
- int tmp;
- char *string;
-
- string=(p+1)->String;
- find_cells_in_range(&(p->Rng));
- tmp=strlen(string);
- while(cell_ptr=next_row_col_in_range(&crow,&ccol)) {
- if(GET_TYP(cell_ptr)!=TYP_STR)
- continue;
- if(!strncmp(cell_ptr->cell_str,string,tmp)) {
- no_more_cells();
- p->Int = 1 + (crow-p->Rng.lr)
- + (ccol-p->Rng.lc)*(1+(p->Rng.hr-p->Rng.lr));
- p->type=TYP_INT;
- return;
- }
- }
- p->Int = 0L;
- p->type=TYP_INT;
- }
-
- static void
- do_hlookup FUN1(struct value *,p)
- {
-
- struct rng *rng = &((p )->Rng);
- double fltval = (p+1)->Float;
- long offset = (p+2)->Int;
-
- CELL *cell_ptr;
- double f;
- CELLREF col;
- CELLREF row;
- char *strptr;
-
- row=rng->lr;
- for(col=rng->lc;col<=rng->hc;col++) {
- if(!(cell_ptr=find_cell(row,col)))
- ERROR(NON_NUMBER);
- switch(GET_TYP(cell_ptr)) {
- case TYP_FLT:
- if(fltval<cell_ptr->cell_flt)
- goto out;
- break;
- case TYP_INT:
- if(fltval<cell_ptr->cell_int)
- goto out;
- break;
- case TYP_STR:
- strptr=cell_ptr->cell_str;
- f=astof(&strptr);
- if(!*strptr && fltval>f)
- goto out;
- else
- ERROR(NON_NUMBER);
- case 0:
- case TYP_BOL:
- case TYP_ERR:
- default:
- ERROR(NON_NUMBER);
- }
- }
- out:
- if(col==rng->lc)
- ERROR(OUT_OF_RANGE);
- --col;
- row=rng->lr+offset;
- if(row>rng->hr)
- ERROR(OUT_OF_RANGE);
- cell_ptr=find_cell(row,col);
- if(!cell_ptr) {
- p->type=0;
- p->Int=0;
- } else {
- p->type=GET_TYP(cell_ptr);
- p->x=cell_ptr->c_z;
- }
- }
-
- static void
- do_vlookup FUN1(struct value *,p)
- {
-
- struct rng *rng = &((p )->Rng);
- double fltval = (p+1)->Float;
- long offset = (p+2)->Int;
-
- CELL *cell_ptr;
- double f;
- CELLREF col;
- CELLREF row;
- char *strptr;
-
- col=rng->lc;
- for(row=rng->lr;row<=rng->hr;row++) {
- if(!(cell_ptr=find_cell(row,col)))
- ERROR(NON_NUMBER);
- switch(GET_TYP(cell_ptr)) {
- case TYP_FLT:
- if(fltval<cell_ptr->cell_flt)
- goto out;
- break;
- case TYP_INT:
- if(fltval<cell_ptr->cell_int)
- goto out;
- break;
- case TYP_STR:
- strptr=cell_ptr->cell_str;
- f=astof(&strptr);
- if(!*strptr && fltval>f)
- goto out;
- else
- ERROR(NON_NUMBER);
- case 0:
- case TYP_BOL:
- case TYP_ERR:
- default:
- ERROR(NON_NUMBER);
- }
- }
- out:
- if(row==rng->lr)
- ERROR(OUT_OF_RANGE);
- --row;
- col=rng->lc+offset;
- if(col>rng->hc)
- ERROR(OUT_OF_RANGE);
-
- cell_ptr=find_cell(row,col);
- if(!cell_ptr) {
- p->type=0;
- p->Int=0;
- } else {
- p->type=GET_TYP(cell_ptr);
- p->x=cell_ptr->c_z;
- }
- }
-
- static void
- do_cell FUN1(struct value *,p)
- {
- int tmp;
-
- tmp=cell(p->Int,(p+1)->Int,(p+2)->String,p);
- if(tmp)
- ERROR(tmp);
- }
-
- struct function cells_funs[] = {
- { C_FN1|C_T, X_A1, "S", do_curcell, "curcell" },
- { C_FN1|C_T, X_A1, "S", do_my, "my" },
- { C_FN3|C_T, X_A3, "IIS", do_cell, "cell" },
-
- { C_FN2, X_A2, "RA", do_member, "member" },
- { C_FN2, X_A2, "RS", do_smember, "smember" },
- { C_FN2, X_A2, "RS", do_members, "members" },
- { C_FN2, X_A2, "RS", do_pmember, "pmember" },
- { C_FN2, X_A2, "RS", do_memberp, "memberp" },
-
- { C_FN3, X_A3, "RFI", do_hlookup, "hlookup" },
- { C_FN3, X_A3, "RFI", do_vlookup, "vlookup" },
-
- { 0, 0, "", 0, 0 },
- };
-
-